
-- 协程

--[[
    Lua 协同程序(coroutine)与线程比较类似：拥有独立的堆栈，独立的局部变量，独立的指令指针，同时又与其它协同程序共享全局变量和其它大部分东西。

    线程与协同程序的主要区别在于，一个具有多个线程的程序可以同时运行几个线程，而协同程序却需要彼此协作的运行。

    在任一指定时刻只有一个协同程序在运行，并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。

    协同程序有点类似同步的多线程，在等待同一个线程锁的几个线程有点类似协同。
--]]

-- 方法
--[[
    coroutine.create() : 创建协程并返回，参数是一个函数，当和 resume 配合使用的时候就唤醒函数调用
    coroutine.resume() ： 重启协程
    coroutine.yield() ： 挂起
    coroutine.status() : 返回协程状态 ： dead,suspended,running
    coroutine.wrap() : 创建协程，但返回的是一个函数引用; 一旦调用这个函数，就进入 coroutine，和 create 功能重复
    coroutine.running() ： 返回正在运行的协程

--]]
-- 创建协程
co = coroutine.create(
        function(i)
            print(i);
        end
)
-- 启动协程
coroutine.resume(co, 1)   -- 1
print(coroutine.status(co))  -- dead

print("------------------------------------------")
-- 创建协程
co = coroutine.wrap(
        function(i)
            print(i);
        end
)
-- 启动协程
co(1)
print("------------------------------------------")

co2 = coroutine.create(
        function()
            for i=1,10 do
                print(i)
                if i == 3 then
                    print(coroutine.status(co2))  --running
                    print(coroutine.running()) --thread:XXXXXX
                end
                coroutine.yield()
            end
        end
)

coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3

print(coroutine.status(co2))   -- suspended  thread: 0000000000f1ed78	false
print(coroutine.running()) -- thread: 0000000000725b08	true

print("------------------------------------------")

-- coroutine.running就可以看出来,coroutine在底层实现就是一个线程。

-- 当create一个coroutine的时候就是在新线程中注册了一个事件。

-- 当使用resume触发事件的时候，create的coroutine函数就被执行了，当遇到yield的时候就代表挂起当前线程，等候再次resume触发事件。

function foo (a)
    print("foo 函数输出", a)
    return coroutine.yield(2 * a) -- 返回  2*a 的值
end

co = coroutine.create(
        function (a , b)
            print("第一次协同程序执行输出", a, b) -- co-body 1 10
            local r = foo(a + 1)

            print("第二次协同程序执行输出", r)
            local r, s = coroutine.yield(a + b, a - b)  -- a，b的值为第一次调用协同程序时传入

            print("第三次协同程序执行输出", r, s)
            return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入
        end
)

print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")

print("------------------------------------------")
